{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Efficiency Analysis \n",
    "\n",
    "\n",
    "## Objective and Prerequisites\n",
    "\n",
    "How can mathematical optimization be used to measure the efficiency of an organization? Find out in this example, where you’ll learn how to formulate an Efficiency Analysis model as a linear programming problem using the Gurobi Python API and then generate an optimal solution with the Gurobi Optimizer.\n",
    "\n",
    "This model is example 22 from the fifth edition of Model Building in Mathematical Programming by H. Paul Williams on pages 278-280 and 335-336.\n",
    "\n",
    "This example is at the intermediate level, where we assume that you know Python and the Gurobi Python API and that you have some knowledge of building mathematical optimization models.\n",
    "\n",
    "**Download the Repository** <br /> \n",
    "You can download the repository containing this and other examples by clicking [here](https://github.com/Gurobi/modeling-examples/archive/master.zip). "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Background\n",
    "\n",
    " The Data Envelopment Analysis (DEA) is a nonparametric problem in operations research and economics whose solution is an estimation of production frontiers. It is used to empirically measure the productive efficiency of decision making units (DMUs). There are a number of linear programming formulations of the DEA problem. Fuller coverage of the subject can be found in Farrell (1957), Charnes et al. (1978) and Thanassoulis et al. (1987). The formulation given by H.P. Williams is described in Land (1991). This formulation is the dual model of a model  commonly used that relies on finding weighted ratios of outputs to inputs. We will use the formulation that is commonly used and can be found in Cooper et al. (2007).\n",
    "\n",
    "The Data Envelopment Analysis has been used to evaluate the performance of many different kinds of entities engaged in many different activities, and in many different contexts in many different countries. Examples include the maintenance activities of U.S. Air Force bases in different geographic locations, or police forces in England and Wales as well as the performance of branch banks in Cyprus and Canada and the efficiency of universities in performing their education and research functions in the U.S., England and France. \n",
    "\n",
    "The DEA approach is concerned with evaluations of *efficiency*. The most common measure of efficiency takes the form of a ratio like the following one:\n",
    "\n",
    "$$\n",
    "\\text{efficiency} = \\frac{\\text{output}}{\\text{input}}\n",
    "$$\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model Formulation\n",
    "\n",
    "Assume there is a set of DMUs. Some common input and output items for each of these DMUs are selected as follows:\n",
    "1. Numerical data are available for each input and output, with the data assumed to be positive, for all DMUs.\n",
    "2. The items (inputs, outputs and choice of DMUs) should reflect an analyst's or a manager's interest in the components that will enter into the relative efficiency evaluations of the DMUs.\n",
    "3. In principle, smaller input amounts are preferable and larger output amounts are preferable so the efficiency scores should reflect these principles.\n",
    "4. The measurement units of the different inputs and outputs do not need to be congruent. Some may involve a number of persons, or areas of floor space, money expended, etc.\n",
    "\n",
    "### Fractional problem formulation\n",
    "The proposed measure of the efficiency of a target DMU $k$ is obtained as the maximum of a ratio of weighted outputs to weighted inputs subject to the condition that the similar ratios for every DMU be less than or equal to one.\n",
    "\n",
    "### Sets and indices\n",
    "\n",
    "$j,k \\in \\text{DMUS}$: Indices and set of DMUs, where $k$ represents the target DMU.\n",
    "\n",
    "$i \\in \\text{Inputs}$: Index and set of inputs.\n",
    "\n",
    "$r \\in \\text{Outputs}$: Index and set of outputs.\n",
    "\n",
    "### Parameters\n",
    "\n",
    "$\\text{invalue}_{i,j} > 0$: Value of input $i$ for DMU $j$.\n",
    "\n",
    "$\\text{outvalue}_{r,j} > 0$: Value of output $r$ for DMU $j$.\n",
    "\n",
    "### Decision Variables\n",
    "\n",
    "$u_{r} \\geq 0$: Weight of output $r$.\n",
    "\n",
    "$v_{i} \\geq 0$: Weight of input  $i$.\n",
    "\n",
    "### Objective function\n",
    "\n",
    "**Target DMU Efficiency**: Maximize efficiency at the target DMU $k$.\n",
    "\n",
    "$$\n",
    "\\text{Maximize} \\quad E_k = \n",
    "\\frac{\\sum_{r \\in \\text{Outputs}} \\text{outvalue}_{r,k}*u_{r}}{\\sum_{i \\in \\text{Inputs}} \\text{invalue}_{i,k}*v_{i}}\n",
    "\\tag{FP0}\n",
    "$$\n",
    "\n",
    "\n",
    "### Constraints\n",
    "\n",
    "**Efficiency ratios**: The efficiency of a DMU is a number between $[0,1]$.\n",
    "\n",
    "\\begin{equation}\n",
    "\\frac{\\sum_{r \\in \\text{Outputs}} \\text{outvalue}_{r,j}*u_{r}}{\\sum_{i \\in \\text{Inputs}} \\text{invalue}_{i,j}*v_{i}}\n",
    " \\leq 1 \\quad \\forall j \\in \\text{DMUS}\n",
    " \\tag{FP1}\n",
    "\\end{equation}\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Linear programming problem formulation\n",
    "\n",
    "This linear programming formulation can be found in the book by Cooper et al. (2007).\n",
    "\n",
    "### Objective function\n",
    "\n",
    "**Target DMU Efficiency**: Maximize efficiency at the target DMU $k$.\n",
    "\n",
    "$$\n",
    "\\text{Maximize} \\quad E_k = \\sum_{r \\in \\text{Outputs}} \\text{outvalue}_{r,k}*u_{r}\n",
    "\\tag{LP0}\n",
    "$$\n",
    "\n",
    "\n",
    "### Constraints\n",
    "\n",
    "**Efficiency ratio**: The efficiency of a DMU is a number between $[0,1]$.\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{r \\in \\text{Outputs}} \\text{outvalue}_{r,j}*u_{r} -\n",
    "\\sum_{i \\in \\text{Inputs}} \\text{invalue}_{i,k}*v_{i}\n",
    " \\leq 0  \\quad \\forall j \\in \\text{DMUS}\n",
    "\\tag{LP1}\n",
    "\\end{equation}\n",
    "\n",
    "**Normalization**: This constraint ensures that the denominator of the objective function of the fractional problem is equal to one.\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{i \\in \\text{Inputs}} \\text{invalue}_{i,k}*v_{i} = 1 \n",
    "\\tag{LP2}\n",
    "\\end{equation}\n",
    "\n",
    "It is easy to verify that the fractional problem and the linear programming problem are equivalent. Let's assume that the denominator of the efficiency ratio constraints of the fractional problem is positive for all DMUs, then we can obtain the constraints $LP1$ by multiplying both sides of the constraints $FP1$ by the denominator. Next, we set the denominator of $FP0$ eqaul to 1 and define constraint $LP2$, and then maximize the numerator, resulting in the objective function $LP0$.\n",
    "\n",
    "### Definition of efficiency\n",
    "\n",
    "1. $DMU_k$ is efficient if the optimal objective function value $E_{k}^{*} = 1$.\n",
    "2. Otherwise, $DMU_k$ is inefficient."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Problem Description\n",
    "\n",
    "A car manufacturer wants to evaluate the efficiencies of different garages that have been granted a license to sell its cars. Each garage has a certain number of measurable ‘inputs’:\n",
    "* Staff \n",
    "* Showroom Space\n",
    "* Population in category 1\n",
    "* Population in category 2\n",
    "* Enquiries Alpha model\n",
    "* Enquiries Beta model\n",
    "\n",
    "Each garage also has a certain number of measurable ‘outputs’:\n",
    "* Number Sold of different brands of car \n",
    "* annual Profit\n",
    "\n",
    "The following table gives the inputs and outputs for each of the 28 franchised garages. \n",
    "\n",
    "![inputOutput1](inputOutput1.PNG)\n",
    "![inputOutput2](inputOutput2.PNG)\n",
    "\n",
    "The goal is to identify efficient and inefficient garages and their input-output weights. In order to solve this problem, it is necessary to solve the LP model for each garage."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Python Implementation\n",
    "\n",
    "We import the Gurobi Python Module and other Python libraries.\n",
    "\n",
    "### Helper Functions\n",
    "\n",
    "* `solve_DEA` builds and solves the LP model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install gurobipy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from itertools import product\n",
    "\n",
    "import gurobipy as gp\n",
    "from gurobipy import GRB\n",
    "\n",
    "# tested with Python 3.7.0 & Gurobi 9.1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def solve_DEA(target, verbose=True):\n",
    "    # input-output values for the garages\n",
    "    inattr = ['staff', 'showRoom', 'Population1', 'Population2', 'alphaEnquiries', 'betaEnquiries']\n",
    "    outattr = ['alphaSales', 'BetaSales', 'profit']\n",
    "    \n",
    "    dmus, inputs, outputs = gp.multidict({\n",
    "        'Winchester': [{'staff': 7, 'showRoom': 8, 'Population1': 10, 'Population2': 12, 'alphaEnquiries': 8.5, 'betaEnquiries': 4}, {'alphaSales': 2, 'BetaSales': 0.6, 'profit': 1.5}],\n",
    "        'Andover': [{'staff': 6, 'showRoom': 6, 'Population1': 20, 'Population2': 30, 'alphaEnquiries': 9, 'betaEnquiries': 4.5}, {'alphaSales': 2.3, 'BetaSales': 0.7, 'profit': 1.6}],\n",
    "        'Basingstoke': [{'staff': 2, 'showRoom': 3, 'Population1': 40, 'Population2': 40, 'alphaEnquiries': 2, 'betaEnquiries': 1.5}, {'alphaSales': 0.8, 'BetaSales': 0.25, 'profit': 0.5}],\n",
    "        'Poole': [{'staff': 14, 'showRoom': 9, 'Population1': 20, 'Population2': 25, 'alphaEnquiries': 10, 'betaEnquiries': 6}, {'alphaSales': 2.6, 'BetaSales': 0.86, 'profit': 1.9}],\n",
    "        'Woking': [{'staff': 10, 'showRoom': 9, 'Population1': 10, 'Population2': 10, 'alphaEnquiries': 11, 'betaEnquiries': 5}, {'alphaSales': 2.4, 'BetaSales': 1, 'profit': 2}],\n",
    "        'Newbury': [{'staff': 24, 'showRoom': 15, 'Population1': 15, 'Population2': 13, 'alphaEnquiries': 25, 'betaEnquiries': 1.9}, {'alphaSales': 8, 'BetaSales': 2.6, 'profit': 4.5}],\n",
    "        'Portsmouth': [{'staff': 6, 'showRoom': 7, 'Population1': 50, 'Population2': 40, 'alphaEnquiries': 8.5, 'betaEnquiries': 3}, {'alphaSales': 2.5, 'BetaSales': 0.9, 'profit': 1.6}],\n",
    "        'Alresford': [{'staff': 8, 'showRoom': 7.5, 'Population1': 5, 'Population2': 8, 'alphaEnquiries': 9, 'betaEnquiries': 4}, {'alphaSales': 2.1, 'BetaSales': 0.85, 'profit': 2}],\n",
    "        'Salisbury': [{'staff': 5, 'showRoom': 5, 'Population1': 10, 'Population2': 10, 'alphaEnquiries': 5, 'betaEnquiries': 2.5}, {'alphaSales': 2, 'BetaSales': 0.65, 'profit': 0.9}],\n",
    "        'Guildford': [{'staff': 8, 'showRoom': 10, 'Population1': 30, 'Population2': 35, 'alphaEnquiries': 9.5, 'betaEnquiries': 4.5}, {'alphaSales': 2.05, 'BetaSales': 0.75, 'profit': 1.7}],\n",
    "        'Alton': [{'staff': 7, 'showRoom': 8, 'Population1': 7, 'Population2': 8, 'alphaEnquiries': 3, 'betaEnquiries': 2}, {'alphaSales': 1.9, 'BetaSales': 0.70, 'profit': 0.5}],\n",
    "        'Weybridge': [{'staff': 5, 'showRoom': 6.5, 'Population1': 9, 'Population2': 12, 'alphaEnquiries': 8, 'betaEnquiries': 4.5}, {'alphaSales': 1.8, 'BetaSales': 0.63, 'profit': 1.4}],\n",
    "        'Dorchester': [{'staff': 6, 'showRoom': 7.5, 'Population1': 10, 'Population2': 10, 'alphaEnquiries': 7.5, 'betaEnquiries': 4}, {'alphaSales': 1.5, 'BetaSales': 0.45, 'profit': 1.45}],\n",
    "        'Bridport': [{'staff': 11, 'showRoom': 8, 'Population1': 8, 'Population2': 10, 'alphaEnquiries': 10, 'betaEnquiries': 6}, {'alphaSales': 2.2, 'BetaSales': 0.65, 'profit': 2.2}],\n",
    "        'Weymouth': [{'staff': 4, 'showRoom': 5, 'Population1': 10, 'Population2': 10, 'alphaEnquiries': 7.5, 'betaEnquiries': 3.5}, {'alphaSales': 1.8, 'BetaSales': 0.62, 'profit': 1.6}],\n",
    "        'Portland': [{'staff': 3, 'showRoom': 3.5, 'Population1': 3, 'Population2': 20, 'alphaEnquiries': 2, 'betaEnquiries': 1.5}, {'alphaSales': 0.9, 'BetaSales': 0.35, 'profit': 0.5}],\n",
    "        'Chichester': [{'staff': 5, 'showRoom': 5.5, 'Population1': 8, 'Population2': 10, 'alphaEnquiries': 7, 'betaEnquiries': 3.5}, {'alphaSales': 1.2, 'BetaSales': 0.45, 'profit': 1.3}],\n",
    "        'Petersfield': [{'staff': 21, 'showRoom': 12, 'Population1': 6, 'Population2': 6, 'alphaEnquiries': 15, 'betaEnquiries': 8}, {'alphaSales': 6, 'BetaSales': 0.25, 'profit': 2.9}],\n",
    "        'Petworth': [{'staff': 6, 'showRoom': 5.5, 'Population1': 2, 'Population2': 2, 'alphaEnquiries': 8, 'betaEnquiries': 5}, {'alphaSales': 1.5, 'BetaSales': 0.55, 'profit': 1.55}],\n",
    "        'Midhurst': [{'staff': 3, 'showRoom': 3.6, 'Population1': 3, 'Population2': 3, 'alphaEnquiries': 2.5, 'betaEnquiries': 1.5}, {'alphaSales': 0.8, 'BetaSales': 0.20, 'profit': 0.45}],\n",
    "        'Reading': [{'staff': 30, 'showRoom': 29, 'Population1': 120, 'Population2': 80, 'alphaEnquiries': 35, 'betaEnquiries': 20}, {'alphaSales': 7, 'BetaSales': 2.5, 'profit': 8}],\n",
    "        'Southampton': [{'staff': 25, 'showRoom': 16, 'Population1': 110, 'Population2': 80, 'alphaEnquiries': 27, 'betaEnquiries': 12}, {'alphaSales': 6.5, 'BetaSales': 3.5, 'profit': 5.4}],\n",
    "        'Bournemouth': [{'staff': 19, 'showRoom': 10, 'Population1': 90, 'Population2': 22, 'alphaEnquiries': 25, 'betaEnquiries': 13}, {'alphaSales': 5.5, 'BetaSales': 3.1, 'profit': 4.5}],\n",
    "        'Henley': [{'staff': 7, 'showRoom': 6, 'Population1': 5, 'Population2': 7, 'alphaEnquiries': 8.5, 'betaEnquiries': 4.5}, {'alphaSales': 1.2, 'BetaSales': 0.48, 'profit': 2}],\n",
    "        'Maidenhead': [{'staff': 12, 'showRoom': 8, 'Population1': 7, 'Population2': 10, 'alphaEnquiries': 12, 'betaEnquiries': 7}, {'alphaSales': 4.5, 'BetaSales': 2, 'profit': 2.3}],\n",
    "        'Fareham': [{'staff': 4, 'showRoom': 6, 'Population1': 1, 'Population2': 1, 'alphaEnquiries': 7.5, 'betaEnquiries': 3.5}, {'alphaSales': 1.1, 'BetaSales': 0.48, 'profit': 1.7}],\n",
    "        'Romsey': [{'staff': 2, 'showRoom': 2.5, 'Population1': 1, 'Population2': 1, 'alphaEnquiries': 2.5, 'betaEnquiries': 1}, {'alphaSales': 0.4, 'BetaSales': 0.1, 'profit': 0.55}],\n",
    "        'Ringwood': [{'staff': 2, 'showRoom': 3.5, 'Population1': 2, 'Population2': 2, 'alphaEnquiries': 1.9, 'betaEnquiries': 1.2}, {'alphaSales': 0.3, 'BetaSales': 0.09, 'profit': 0.4}]\n",
    "    })\n",
    "    \n",
    "    ### Create LP model\n",
    "    model = gp.Model('DEA')\n",
    "    \n",
    "    # Decision variables\n",
    "    wout = model.addVars(outattr, name=\"outputWeight\")\n",
    "    win = model.addVars(inattr, name=\"inputWeight\")\n",
    "\n",
    "    # Constraints\n",
    "    ratios = model.addConstrs( ( gp.quicksum(outputs[h][r]*wout[r] for r in outattr ) \n",
    "                                - gp.quicksum(inputs[h][i]*win[i] for i in inattr ) \n",
    "                                <= 0 for h in dmus ), name='ratios' )\n",
    "    \n",
    "    normalization = model.addConstr((gp.quicksum(inputs[target][i]*win[i] for i in inattr ) == 1 ),\n",
    "                                    name='normalization')\n",
    "    \n",
    "    # Objective function\n",
    "    \n",
    "    model.setObjective( gp.quicksum(outputs[target][r]*wout[r] for r in outattr ), GRB.MAXIMIZE)\n",
    "    \n",
    "    # Run optimization engine\n",
    "    if not verbose:\n",
    "        model.params.OutputFlag = 0\n",
    "    model.optimize()\n",
    "    \n",
    "    # Print results\n",
    "    print(f\"\\nThe efficiency of target DMU {target} is {round(model.objVal,3)}\") \n",
    "    \n",
    "    print(\"__________________________________________________________________\")\n",
    "    print(f\"The weights for the inputs are:\")\n",
    "    for i in inattr:\n",
    "        print(f\"For {i}: {round(win[i].x,3)} \") \n",
    "        \n",
    "    print(\"__________________________________________________________________\")\n",
    "    print(f\"The weights for the outputs are\")\n",
    "    for r in outattr:\n",
    "        print(f\"For {r} is: {round(wout[r].x,3)} \") \n",
    "    print(\"__________________________________________________________________\\n\\n\")  \n",
    "    \n",
    "    return model.objVal"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Input Data\n",
    "We define the list of garages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "dmus = ['Winchester','Andover','Basingstoke', 'Poole', 'Woking','Newbury','Portsmouth','Alresford','Salisbury','Guildford','Alton','Weybridge', 'Dorchester', 'Bridport', 'Weymouth', 'Portland', 'Chichester', 'Petersfield', 'Petworth', 'Midhurst', 'Reading', 'Southampton', 'Bournemouth', 'Henley', 'Maidenhead', 'Fareham', 'Romsey', 'Ringwood']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Output Report\n",
    "\n",
    "We print out the efficiency score of each garage and its associated input and output weights."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using license file c:\\gurobi\\gurobi.lic\n",
      "\n",
      "The efficiency of target DMU Winchester is 0.835\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.012 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.002 \n",
      "For alphaEnquiries: 0.095 \n",
      "For betaEnquiries: 0.02 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.113 \n",
      "For BetaSales is: 0.004 \n",
      "For profit is: 0.404 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Andover is 0.917\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.115 \n",
      "For showRoom: 0.03 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.014 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.399 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Basingstoke is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.429 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.071 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 1.25 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Poole is 0.864\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.019 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.001 \n",
      "For alphaEnquiries: 0.081 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.065 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.366 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Woking is 0.845\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.015 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.001 \n",
      "For alphaEnquiries: 0.062 \n",
      "For betaEnquiries: 0.032 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.218 \n",
      "For profit is: 0.314 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Newbury is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.526 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.222 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Portsmouth is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.149 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.036 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.4 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Alresford is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.002 \n",
      "For alphaEnquiries: 0.098 \n",
      "For betaEnquiries: 0.026 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.081 \n",
      "For BetaSales is: 0.005 \n",
      "For profit is: 0.413 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Salisbury is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.087 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.113 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.5 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Guildford is 0.802\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.014 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.075 \n",
      "For betaEnquiries: 0.036 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.062 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.397 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Alton is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.333 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 1.429 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Weybridge is 0.854\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.149 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.028 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.379 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.122 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Dorchester is 0.867\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.014 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.003 \n",
      "For alphaEnquiries: 0.118 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.11 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.484 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Bridport is 0.982\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.002 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.002 \n",
      "For alphaEnquiries: 0.096 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.06 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.387 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Weymouth is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.25 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.556 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Portland is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.032 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.452 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 2.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Chichester is 0.825\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.011 \n",
      "For showRoom: 0.008 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.002 \n",
      "For alphaEnquiries: 0.125 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.098 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.545 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Petersfield is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.019 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.04 \n",
      "For betaEnquiries: 0.021 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.167 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Petworth is 0.988\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.156 \n",
      "For Population1: 0.058 \n",
      "For Population2: 0.013 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.141 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.501 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Midhurst is 0.889\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.018 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.011 \n",
      "For alphaEnquiries: 0.366 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.294 \n",
      "For BetaSales is: 0.047 \n",
      "For profit is: 1.431 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Reading is 0.984\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.001 \n",
      "For showRoom: 0.006 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.023 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.019 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.106 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Southampton is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.005 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.028 \n",
      "For betaEnquiries: 0.012 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.057 \n",
      "For profit is: 0.149 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Bournemouth is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.1 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.323 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Henley is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.161 \n",
      "For Population1: 0.007 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 0.5 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Maidenhead is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.122 \n",
      "For Population1: 0.004 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.5 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Fareham is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 1.0 \n",
      "For alphaEnquiries: 0.0 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 2.083 \n",
      "For profit is: 0.0 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Romsey is 1.0\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.0 \n",
      "For alphaEnquiries: 0.31 \n",
      "For betaEnquiries: 0.224 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.0 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 1.818 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n",
      "\n",
      "The efficiency of target DMU Ringwood is 0.908\n",
      "__________________________________________________________________\n",
      "The weights for the inputs are:\n",
      "For staff: 0.0 \n",
      "For showRoom: 0.0 \n",
      "For Population1: 0.0 \n",
      "For Population2: 0.013 \n",
      "For alphaEnquiries: 0.512 \n",
      "For betaEnquiries: 0.0 \n",
      "__________________________________________________________________\n",
      "The weights for the outputs are\n",
      "For alphaSales is: 0.299 \n",
      "For BetaSales is: 0.0 \n",
      "For profit is: 2.044 \n",
      "__________________________________________________________________\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Solving DEA model for each DMU\n",
    "\n",
    "performance = {}\n",
    "for h in dmus:    \n",
    "    performance[h] = solve_DEA(h, verbose=False)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Analysis\n",
    "\n",
    "We identify which garages are efficient and which ones are inefficient, and provide the efficiency scores for each garage."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "____________________________________________\n",
      "The efficient DMUs are:\n",
      "The performance value of DMU Newbury is: 1.0\n",
      "The performance value of DMU Alresford is: 1.0\n",
      "The performance value of DMU Salisbury is: 1.0\n",
      "The performance value of DMU Alton is: 1.0\n",
      "The performance value of DMU Weymouth is: 1.0\n",
      "The performance value of DMU Petersfield is: 1.0\n",
      "The performance value of DMU Southampton is: 1.0\n",
      "The performance value of DMU Bournemouth is: 1.0\n",
      "The performance value of DMU Maidenhead is: 1.0\n",
      "The performance value of DMU Fareham is: 1.0\n",
      "The performance value of DMU Romsey is: 1.0\n",
      "The performance value of DMU Basingstoke is: 1.0\n",
      "The performance value of DMU Portsmouth is: 1.0\n",
      "The performance value of DMU Portland is: 1.0\n",
      "The performance value of DMU Henley is: 1.0\n",
      "____________________________________________\n",
      "The inefficient DMUs are:\n",
      "The performance value of DMU Petworth is: 0.988\n",
      "The performance value of DMU Reading is: 0.984\n",
      "The performance value of DMU Bridport is: 0.982\n",
      "The performance value of DMU Andover is: 0.917\n",
      "The performance value of DMU Ringwood is: 0.908\n",
      "The performance value of DMU Midhurst is: 0.889\n",
      "The performance value of DMU Dorchester is: 0.867\n",
      "The performance value of DMU Poole is: 0.864\n",
      "The performance value of DMU Weybridge is: 0.854\n",
      "The performance value of DMU Woking is: 0.845\n",
      "The performance value of DMU Winchester is: 0.835\n",
      "The performance value of DMU Chichester is: 0.825\n",
      "The performance value of DMU Guildford is: 0.802\n"
     ]
    }
   ],
   "source": [
    "# Identifying efficient and inefficient DMUs\n",
    "\n",
    "# Sorting garages in descending efficiency number\n",
    "sorted_performance = {k: v for k, v in sorted(performance.items(), key=lambda item: item[1], reverse = True)}\n",
    "\n",
    "efficient = []\n",
    "inefficient = []\n",
    "\n",
    "for h in sorted_performance.keys():\n",
    "    if sorted_performance[h] >= 0.9999999:\n",
    "        efficient.append(h) \n",
    "    if sorted_performance[h] < 0.9999999:\n",
    "        inefficient.append(h) \n",
    "        \n",
    "print('____________________________________________')\n",
    "print(f\"The efficient DMUs are:\")\n",
    "for eff in efficient:\n",
    "    print(f\"The performance value of DMU {eff} is: {round(performance[eff],3)}\") \n",
    "    \n",
    "print('____________________________________________')\n",
    "print(f\"The inefficient DMUs are:\")\n",
    "for ine in inefficient:\n",
    "    print(f\"The performance value of DMU {ine} is: {round(performance[ine],3)}\") \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "H. Paul Williams, Model Building in Mathematical Programming, fifth edition.\n",
    "\n",
    "Cooper, W. W, L. M. Seiford, K. Tone. (2007) Data Envelopment Analysis: A Comprehensive Text with Models, Applications, References and DEA-Solver Software. Second edition. Springer-Verlag US.\n",
    "\n",
    "Land, A. (1991) Data envelopment analysis, Chapter 5, in Operations Research in Management (eds S.C. Littlechild and M.F. Shutler), Prentice Hall, London.\n",
    "\n",
    "Farrell, M.J. (1957) The measurement of productive efficiency. Journal of the Royal Statistical Society, Series A, 120, 253–290.\n",
    "\n",
    "Charnes, A., Cooper, W.W. and Rhodes, E. (1978) Measuring the efficiency of decision making units. European Journal of Operational Research, 2, 429–444.\n",
    "\n",
    "Thanassoulis, E., Dyson, R.G. and Foster, M.J. (1987) Relative efficiency assessments using data envelopment analysis: an application to data on rates departments. Journal of the Operational Research Society, 5, 397–411.\n",
    "\n",
    "Copyright © 2020 Gurobi Optimization, LLC"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
